import os, pygame

from data import *
import math

TOP_SIDE    = 0
BOTTOM_SIDE = 2
LEFT_SIDE   = 3
RIGHT_SIDE  = 1
SCREEN_WIDTH = 800
SCREEN_HEIGHT = 480
        
def speed_to_side(dx,dy):
    if abs(dx) > abs(dy):
        dy = 0
    else:
        dx = 0
    if dy < 0:
        return 0
    elif dx > 0:
        return 1
    elif dy > 0:
        return 2
    elif dx < 0:
        return 3
    else:
        return 0, 0

class Collidable(pygame.sprite.Sprite):

    def __init__(self, *groups):
        pygame.sprite.Sprite.__init__(self, groups)
        self.collision_groups = []
        self.xoffset = 0
        self.yoffset = 0

    def collide(self, group):
        if group not in self.collision_groups:
            self.collision_groups.append(group)

    def move(self, dx, dy, collide=True):
        if collide:
            if dx!=0:
                dx, dummy = self.__move(dx,0)
            if dy!=0:
                dummy, dy = self.__move(0,dy)
        else:
            self.rect.move_ip(dx, dy)
        return dx, dy

    def clamp_off(self, sprite, side):
        if side == TOP_SIDE:
            self.rect.top = sprite.rect.bottom
        if side == RIGHT_SIDE:
            self.rect.right = sprite.rect.left
        if side == BOTTOM_SIDE:
            self.rect.bottom = sprite.rect.top
        if side == LEFT_SIDE:
            self.rect.left = sprite.rect.right

    def __move(self,dx,dy):
        oldr = self.rect
        self.rect.move_ip(dx, dy)
        side = speed_to_side(dx, dy)

        for group in self.collision_groups:
            for spr in group:
                if spr.rect.colliderect(self.rect):
                    self.on_collision(side, spr, group)

        return self.rect.left-oldr.left,self.rect.top-oldr.top

    def on_collision(self, side, sprite, group):
        self.clamp_off(sprite, side)

    def draw(self, surf):
        surf.blit(self.image, (self.rect[0]+self.xoffset, self.rect[1]+self.yoffset))

class Player(Collidable):
    def __init__(self, top, left, events):
        Collidable.__init__(self, self.groups)
        self.images     = [loadImage("bird%d.png" % i) for i in range(1,8)]
        self.image      = self.images[0]
        self.rect       = self.image.get_rect()
        self.rect.top   = top
        self.rect.left  = left
        self.frame      = 0
        self.x          = 0
        self.y          = 0
        self.events     = events
        
    def shoot(self):
        PlayerDef((self.rect.centerx - 30), self.rect.centery)
    
    def update(self):          
        self.frame += 1
        speed       = 10 - self.x
        self.image  = self.images[self.frame/speed%7]

        for event in self.events:
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_SPACE:
                    self.shoot()
                if event.key == pygame.K_UP:
                    self.y += -1
                if event.key == pygame.K_DOWN:
                    self.y += 1
                if event.key == pygame.K_LEFT:
                    self.x += -1
                if event.key == pygame.K_RIGHT:
                    self.x += 1
            if event.type == pygame.KEYUP:
                if event.key == pygame.K_UP:
                    self.y = 0
                if event.key == pygame.K_DOWN:
                    self.y = 0
                if event.key == pygame.K_LEFT:
                    self.x = 0
                if event.key == pygame.K_RIGHT:
                    self.x = 0
        
        if self.rect.top < 0:
            self.rect.top = 0
        if self.rect.bottom > SCREEN_HEIGHT:
            self.rect.bottom = SCREEN_HEIGHT
        if self.rect.left < 0:
            self.rect.left = 0
            
        self.move(2*self.x, 2*self.y)
        
    def blink(self):
        print "blink"
        
class PlayerDef(Collidable):
    def __init__(self, x, y):
        Collidable.__init__(self, self.groups)
        self.image = loadImage("ball.png")
        self.rect = self.image.get_rect()
        #self.rect.midleft = startpos
        self.rect.centery = y
        self.rect.centerx = x
        
    def update (self):
        if self.rect.top >= SCREEN_HEIGHT:
            self.kill()
        else:
            self.rect.move_ip((0, 4))

class Cannon(Collidable):
    def __init__(self, pos, player):
        Collidable.__init__(self, self.groups)
        self.image = loadImage("cannon.png")
        self.rect = self.image.get_rect(topleft = pos)
        self.player = player
        self.frame = 0
        self.shotFrame = -90
        
    def update(self):
        if (self.frame - self.shotFrame) >= 90:
            CannonDef((self.rect.centerx - 11) , (self.rect.centery - 11), self.rect.center, self.player.rect.center )
            self.shotFrame = self.frame
        
        self.frame += 1
        
class Cannon2(Collidable):
    def __init__(self, pos, player):
        Collidable.__init__(self, self.groups)
        self.image = loadImage("cannon2.png")
        self.rect = self.image.get_rect(topleft = pos)
        self.player = player
        self.frame = 0
        self.shotFrame = -90
        
    def update(self):
        if (self.frame - self.shotFrame) >= 90:
            CannonDef((self.rect.centerx + 11) , (self.rect.centery - 11), self.rect.center, self.player.rect.center )
            self.shotFrame = self.frame
        
        self.frame += 1
        
            
class Explosion(Collidable):
    def __init__(self, pos):
        Collidable.__init__(self, self.groups)
        self.image = loadImage("explosion.png")
        self.rect = self.image.get_rect()
        self.rect.center = pos
        self.frame = 0
        
    def update(self):
        if self.frame < 30: 
            self.frame += 1
        else:
            self.kill()
            self.frame = 0
               
class CannonDef(Collidable):
    def __init__(self, x, y, ccenter, pcenter):
        Collidable.__init__(self, self.groups)
        self.image = loadImage("ball.png")
        self.rect = self.image.get_rect()
        self.speed = 4
        self.initx = x
        self.inity = y
        self.x = x
        self.y = y
        self.ccenter = ccenter
        self.pcenter = pcenter
        self.updatex = 0
        self.updatey = 0
        self.frame = 0
        self.calcSteps()
        
    def calcSteps(self):
        playerx, playery = self.pcenter;
        
        dx = self.x - playerx
        dy = self.y - playery
        
        rad = math.atan2(dy, dx) + math.pi
        
        self.updatex = math.cos(rad) * self.speed
        self.updatey = math.sin(rad) * self.speed

        
    def update(self):
        self.x += (self.updatex)
        self.y += (self.updatey)
        
        self.rect.centerx = self.updatex
        self.rect.centery = self.updatey
               
        self.rect.move_ip((self.x, self.y))
            
class Brick(Collidable):
    def __init__(self, pos):
        Collidable.__init__(self, self.groups)
        self.image = loadImage("steen.png")
        self.rect = self.image.get_rect(topleft = pos)
        
class Grass(Collidable):
    def __init__(self, pos):
        Collidable.__init__(self, self.groups)
        self.image = loadImage("grass.png")
        self.rect = self.image.get_rect(topleft = pos)
        
class Cloud(Collidable):
    def __init__(self, pos):
        Collidable.__init__(self, self.groups)
        self.image = loadImage("cloud.png")
        #self.image.set_alpha(120)
        self.rect = self.image.get_rect(topleft = pos)
        
class Finish(Collidable):
    def __init__(self, pos):
        Collidable.__init__(self, self.groups)
        self.image = loadImage("finish.png")
        self.rect = self.image.get_rect(topleft = pos)
        
class FinishLine(Collidable):
    def __init__(self, pos):
        Collidable.__init__(self, self.groups)
        self.image = loadImage("finishline.png")
        self.rect = self.image.get_rect(topleft = pos)